package org.xu.logic;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.xu.bo.EnumOptionResponse;
import org.xu.bo.ExcelExportBO;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
// @Service
public class ExportLogicImpl implements ExportLogic{

    /**
     * 导出
     * @param workbook excel
     * @param response 响应
     */
    protected static void write(HSSFWorkbook workbook, HttpServletResponse response){
        try {
            String fileType = ".xlsx";
            String fileName = "excel" + fileType;
            String attachment = "attachment; filename=" + URLEncoder.encode(fileName,"UTF-8");
            response.setHeader("Content-disposition", attachment);
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("UTF-8");
            OutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("导出Excel失败！");
        }
    }

    @Override
    public void generateExcel(HttpServletResponse response) {

    }

    // -------------
    /**
     * 表头
     */
    private List<String> headerNames;
    /**
     * 工作簿
     */
    private Workbook workBook;
    /**
     * excel工作表
     */
    private Sheet sheet;

    /**
     * 初始化表头信息
     */
    private void initHeader() {
        // 创建第一行
        Row row = sheet.createRow(0);
        Cell cell = null;
        // 创建表头
        for (int i = 0; i < headerNames.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(headerNames.get(i));
            setHeaderCellStyle(cell);
        }
    }

    /**
     * 设置表头单元格样式
     *
     * @param cell 单元格
     */
    public void setHeaderCellStyle(Cell cell) {
        // 设置样式
        CellStyle cellStyle = workBook.createCellStyle();
        // 设置字体居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        // 设置字体
        Font font = workBook.createFont();
        font.setFontName(HSSFFont.FONT_ARIAL);
        // 设置加粗
        font.setBold(true);
        // 设置字号
        font.setFontHeightInPoints((short) 13);
        cellStyle.setFont(font);
        cell.setCellStyle(cellStyle);
    }

    /**
     *
     * @param dataList 数据,每一个map都是一行
     * @param keys key[i]代表从map中获取keys[i]的值作为第i列的值,如果传的是null默认取表头
     */
    public void createTableRows(List<Map<String,Object>> dataList, String[] keys) {
        for (int i = 0, length_1 = dataList.size(); i < length_1; i++) {
            Map<String, Object> data = dataList.get(i);
            Row row = sheet.createRow(i + 1);
            Cell cell = null;
            for (int j = 0, length_2 = keys.length; j < length_2; j++) {
                // 单元格获取map中的key
                String key = keys[j];
                String value = MapUtils.getString(data, key, "");
                cell = row.createCell(j);
                cell.setCellType(CellType.STRING);
                cell.setCellValue(value);
            }

        }
    }

    /**
     * 根据表头自动调整列宽度
     */
    public void autoAllSizeColumn() {
        // 如果是SXSSFSheet，需要调用trackAllColumnsForAutoSizing方法一次
        if (sheet instanceof SXSSFSheet) {
            SXSSFSheet tmpSheet = (SXSSFSheet) sheet;
            tmpSheet.trackAllColumnsForAutoSizing();
        }
        for (int i = 0, length = headerNames.size(); i < length; i++) {
            sheet.autoSizeColumn(i);
        }
    }

    /**
     * 将数据写出到excel中
     */
    public void exportExcel(OutputStream outputStream) {
        // 导出之前先自动设置列宽
        this.autoAllSizeColumn();
        try {
            workBook.write(outputStream);
        } catch (IOException e) {
            log.error(" exportExcel error", e);
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    public ExportLogicImpl(ExcelExportBO exportBO) {
        this.headerNames = exportBO.getHeaderList().stream().map(EnumOptionResponse::getName).collect(Collectors.toList());
        // 创建一个工作簿 内存中保持100条数据, 超出的部分刷新到磁盘上
        workBook = new SXSSFWorkbook(10000);
        sheet = workBook.createSheet(exportBO.getSheetName());
        initHeader();
    }


    private static void test() {
        ExcelExportBO exportBO = new ExcelExportBO();
        exportBO.setSheetName("人员基本信息");
        List<Map<String,Object>> dataList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Map data = new HashMap<>();
            data.put("name", "张三" + i);
            data.put("age", "15" + i);
            dataList.add(data);
        }
        List<EnumOptionResponse> headerList = new ArrayList<>();
        EnumOptionResponse code = new EnumOptionResponse();
        code.setCode("name");
        code.setName("姓名");
        headerList.add(code);
        EnumOptionResponse code2 = new EnumOptionResponse();
        code2.setCode("code");
        code2.setName("年龄");
        headerList.add(code2);
        exportBO.setHeaderList(headerList);
        ExportLogicImpl hssfWorkExcel = new ExportLogicImpl(exportBO);

        hssfWorkExcel.createTableRows(dataList, new String[] { "name", "age" });
        try {
            hssfWorkExcel.exportExcel(new FileOutputStream(new File("D:\\tmp\\test1.xlsx")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        test();
    }

}
